package com.qianli.cashmama.trade.integration.pay.impl;

import com.alibaba.fastjson.JSON;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.common.utils.TimeUtils;
import com.fqgj.xjd.user.client.request.UserResident;
import com.fqgj.xjd.user.client.response.UserBankInfo;
import com.fqgj.xjd.user.client.response.UserInfo;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.qianli.cashmama.pay.client.domain.payment.request.Contact;
import com.qianli.cashmama.pay.client.domain.payment.request.ExtraData;
import com.qianli.cashmama.pay.client.domain.payment.request.PaymentPushRequest;
import com.qianli.cashmama.pay.client.domain.payment.response.PaymentPushResponse;
import com.qianli.cashmama.pay.client.domain.query.request.FundAccountRequest;
import com.qianli.cashmama.pay.client.domain.query.response.FundAccountInfoResponse;
import com.qianli.cashmama.pay.client.service.FundManagerService;
import com.qianli.cashmama.pay.client.service.PayService;
import com.qianli.cashmama.pay.client.service.PaymentPushService;
import com.qianli.cashmama.pay.client.service.QueryService;
import com.qianli.cashmama.trade.common.dto.UserTradeSnapshotDto;
import com.qianli.cashmama.trade.common.enums.TradeBorrowDurationEnum;
import com.qianli.cashmama.trade.common.utils.TradeConfigUtil;
import com.qianli.cashmama.trade.dao.TTaskRecordDao;
import com.qianli.cashmama.trade.entity.TTaskRecordEntity;
import com.qianli.cashmama.trade.entity.TTradeOpenOrderEntity;
import com.qianli.cashmama.trade.integration.audit.AuditIntegrationService;
import com.qianli.cashmama.trade.integration.pay.PayIntegrationService;
import com.qianli.cashmama.trade.integration.pay.dto.TradePayDto;
import com.qianli.cashmama.trade.integration.user.UserIntegrationService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * Created with IntelliJ IDEA.
 * User: sm
 * Date: 2017/7/24
 * Time: 上午9:17
 */
@Service
public class PayIntegrationServiceImpl implements PayIntegrationService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PayIntegrationServiceImpl.class);

    @Autowired
    private PaymentPushService paymentPushService;

    @Autowired
    private PayService payService;

    @Autowired
    private QueryService queryService;

    @Autowired
    private FundManagerService fundManagerService;

    @Autowired
    private TTaskRecordDao tTaskRecordDao;

    @Autowired
    UserIntegrationService userIntegrationService;

    @Autowired
    AuditIntegrationService auditIntegrationService;

    @Autowired
    private TradeConfigUtil configUtil;

    @Override
    public boolean pushTradeToPay(TradePayDto tradePayDto, String productCategory) {
        try {
            // 扩展信息
            ExtraData extraData = getExtraData(tradePayDto);
            // 推单到支付参数
            PaymentPushRequest request = getPaymentPushRequest(tradePayDto, productCategory, extraData);
            LOGGER.info("推送给支付的数据,request:{}", JSON.toJSONString(request));
            Response<PaymentPushResponse> responseResponse = paymentPushService.pushOrder(request);
            LOGGER.info("推送给支付的数据,response:{}", JSON.toJSONString(responseResponse));
            return responseResponse.isSuccess();
        } catch (Exception e) {
            LOGGER.error("推送到支付失败,tradeNo:{}", tradePayDto.getTradeNo(), e);
            return false;
        }
    }

    /**
     * 根据资金账号查询NBFC信息
     */
    @Override
    public FundAccountInfoResponse getNbfcByFundCode(Integer fundCode) {
        FundAccountRequest fundAccountPayRequest = new FundAccountRequest();
        fundAccountPayRequest.setFundCode(fundCode);
        Response<FundAccountInfoResponse> fundAccountInfo = fundManagerService.getFundAccountInfo(fundAccountPayRequest);
        return fundAccountInfo.getData();
    }


    private ExtraData getExtraData(TradePayDto tradePayDto) {
        ExtraData extraData = new ExtraData();
        extraData.setBorrowerProvince(tradePayDto.getUserProvince())
                .setBorrowerCity(tradePayDto.getUserCity())
                .setBorrowerAddress(tradePayDto.getUserAddress())
                .setBankCardPhoneNum(tradePayDto.getSignMobile())

                .setCompanyName(tradePayDto.getCompanyName())
                .setMarriageStatus(tradePayDto.getMarriageStatus())
                .setZmScore(tradePayDto.getZmScore())
                .setIdentityCard(tradePayDto.getIdFrontUrl())
                .setReverseCard(tradePayDto.getIdBackUrl())
                .setLife(tradePayDto.getLivePicUrl());

        Contact familyContact = new Contact()
                .setContactMobile(tradePayDto.getUserEmergencyContact().getUserFamilyContact().getMobile())
                .setContactName(tradePayDto.getUserEmergencyContact().getUserFamilyContact().getContactName())
                .setContactRelation(tradePayDto.getUserEmergencyContact().getUserFamilyContact().getUserContactFamilyTypeEnum().getDesc());

        Contact friendContact = new Contact()
                .setContactMobile(tradePayDto.getUserEmergencyContact().getUserFriendContact().getMobile())
                .setContactName(tradePayDto.getUserEmergencyContact().getUserFriendContact().getContactName())
                .setContactRelation(tradePayDto.getUserEmergencyContact().getUserFriendContact().getUserContactFriendTypeEnum().getDesc());

        List<Contact> contactList = new ArrayList<>();
        contactList.add(familyContact);
        contactList.add(friendContact);

        extraData.setContactList(contactList);
        return extraData;
    }

    private PaymentPushRequest getPaymentPushRequest(TradePayDto tradePayDto, String productCategory, ExtraData extraData) {

        UserTradeSnapshotDto userTradeSnapshotDto = userIntegrationService.getUserTradeSnapshotInfoByUserCode(tradePayDto.getUserCode(), tradePayDto.getProductCode());
        UserInfo userInfo = Optional.ofNullable(userTradeSnapshotDto.getUserInfo()).orElseGet(UserInfo::new);
        UserResident userResident = Optional.ofNullable(userInfo.getUserResident()).orElseGet(UserResident::new);
        UserBankInfo userBankInfo = Optional.ofNullable(userTradeSnapshotDto.getUserBankInfo()).orElseGet(UserBankInfo::new);

        BigDecimal arrivalAmount = tradePayDto.getReceivedCapital();
        BigDecimal contractAmount = tradePayDto.getBorrowCapital();
        String pushMoneyLimitSwitch = configUtil.getPayMoneyLimit();
        if (StringUtils.isEmpty(pushMoneyLimitSwitch) || pushMoneyLimitSwitch.equals("1")) {
            arrivalAmount = BigDecimal.valueOf(1);
            contractAmount = BigDecimal.valueOf(1);
        }

        int days = getDays(tradePayDto);

        PaymentPushRequest request = new PaymentPushRequest();
        request.setProductCategoryCode(productCategory);
        request.setAcctName(tradePayDto.getUserName());
        request.setApplyTime(new Date());
        request.setArrivalAmount(arrivalAmount.toString());
        request.setBankName(tradePayDto.getBankName());

        request.setBizNo(tradePayDto.getBizNo());
        request.setCardNo(tradePayDto.getBankNo());
        request.setContractAmount(contractAmount.toString());
        request.setDuration(tradePayDto.getTotalPeriod());

        request.setIdNo(tradePayDto.getIdentityNo());
        request.setOrderId(tradePayDto.getTradeId().toString());
        request.setNotifyUrl(configUtil.getPaymentCallbackUrl());
        request.setVerifiedTime(tradePayDto.getAuditDate() == null ? new Date() : tradePayDto.getAuditDate());

        request.setChannelFrom(productCategory);
        request.setInfoOrder("cashmama payment");
        request.setExtraData(extraData);
        request.setProductCode(tradePayDto.getProductCode());
        request.setLoanDays(days);

        // push to pay request
        request.setBeneficiaryIFSC(userBankInfo.getCode());
        request.setAddress(userResident.getAddress());
        request.setMobile(userInfo.getUser().getMobile());
        request.setEmail(tradePayDto.getEmail());
        request.setUserCode(tradePayDto.getUserCode());
        request.setFundSideCode(tradePayDto.getCapitalCode());
        request.setSignDate(tradePayDto.getSignDate());

        return request;

    }

    private int getDays(TradePayDto tradePayDto) {
        Date repaymentDate;
        int periodLength = tradePayDto.getPeriodLength();
        int totalPeriod = tradePayDto.getTotalPeriod();

        int days = 0;
        TradeBorrowDurationEnum tradeBorrowDurationEnum = tradePayDto.getBorrowDurationEnum();
        switch (tradeBorrowDurationEnum) {
            case DAY:
                days = tradePayDto.getPeriodLength();
                break;
            case WEEK:
                days = tradePayDto.getPeriodLength() * 7;
                break;
            case YEAR:
                repaymentDate = DateUtil.getMonthNowDate(periodLength * totalPeriod);
                days = TimeUtils.diffDays(TimeUtils.getDate("yyyy-MM-dd", new Date()), TimeUtils.getDate("yyyy-MM-dd", repaymentDate));
                break;
            default:
                break;
        }
        return days;
    }

    private String getBirthday(String birthday) {
        if (StringUtils.isBlank(birthday)) {
            return birthday;
        }
        List<String> ddMMyy = Splitter.on("-").trimResults().omitEmptyStrings().splitToList(birthday);
        ArrayList<String> strings = Lists.newArrayList(ddMMyy.get(2), ddMMyy.get(1), ddMMyy.get(0));
        return Joiner.on("-").join(strings);
    }

    private void addTaskRecord(Long taskId, String taskContent) {
        TTaskRecordEntity tTaskRecordEntity = new TTaskRecordEntity();
        tTaskRecordEntity.setTaskId(taskId + "");
        tTaskRecordEntity.setRequest(taskContent);
        tTaskRecordDao.insert(tTaskRecordEntity);
    }


    @Override
    public boolean pushTradeToPay(TTradeOpenOrderEntity entity, String productCategory) {
        try {
            // 推单到支付参数
            PaymentPushRequest request = getPaymentPushRequest(entity, productCategory);
            LOGGER.info("三方风控审核通过订单推送给支付的数据,request:{}", JSON.toJSONString(request));
            Response<PaymentPushResponse> responseResponse = paymentPushService.pushOrder(request);
            LOGGER.info("三方风控审核通过订单推送给支付的数据,response:{}", JSON.toJSONString(responseResponse));
            return responseResponse.isSuccess();
        } catch (Exception e) {
            LOGGER.error("三方风控审核通过订单推送到支付失败,tradeNo:{}", entity.getTradeNo(), e);
            return false;
        }
    }

    private PaymentPushRequest getPaymentPushRequest(TTradeOpenOrderEntity entity, String productCategory) {

        BigDecimal arrivalAmount = entity.getArrivalAmount();
        BigDecimal contractAmount = entity.getContractAmount();
        String pushMoneyLimitSwitch = configUtil.getPayMoneyLimit();
        if (StringUtils.isEmpty(pushMoneyLimitSwitch) || pushMoneyLimitSwitch.equals("1")) {
            arrivalAmount = BigDecimal.valueOf(1);
            contractAmount = BigDecimal.valueOf(1);
        }

        PaymentPushRequest request = new PaymentPushRequest();
        request.setProductCategoryCode(productCategory);
        request.setAcctName(entity.getAcctName());
        request.setApplyTime(new Date());
        request.setArrivalAmount(arrivalAmount.toString());
        request.setBankName(entity.getBankName());

        request.setBizNo(entity.getTradeNo());
        request.setCardNo(entity.getBankNo());
        request.setContractAmount(contractAmount.toString());
        request.setDuration(1);

        request.setIdNo(entity.getBankNo());
        request.setOrderId(entity.getId().toString());
        request.setNotifyUrl(configUtil.getPaymentCallbackUrl());
        request.setVerifiedTime(new Date());

        request.setChannelFrom(productCategory);
        request.setInfoOrder("open_api_payment");
        request.setLoanDays(7);//暂定为7

        // push to pay request
        request.setBeneficiaryIFSC(entity.getIfscCode());
        request.setMobile(entity.getPhone());
        request.setEmail(entity.getEmail());
        request.setUserCode(entity.getUserCode());
        request.setFundSideCode(null);
        request.setSignDate(new Date());

        return request;
    }
}
